/**
* DefaultTextModel - An Implementation of TextModel
*
* Copyright (c) 2002
* Marty Phelan, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.taursys.model;
import java.text.Format;
import java.text.MessageFormat;
import java.text.ChoiceFormat;
import com.taursys.util.DataTypes;
import com.taursys.util.UnsupportedConversionException;
import com.taursys.util.UnsupportedDataTypeException;
import java.text.ParseException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.lang.reflect.InvocationTargetException;
import java.lang.IllegalAccessException;
import java.beans.IntrospectionException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.util.Vector;
/**
* This class implements the TextModel interface and is designed to work with Parameter and Fields.
* This model stores its value in a ValueHolder object under a propertyName.
* This model converts the value to/from text using a given format and formatPattern.
* By default, this model uses a VariantValueHolder.
*/
public class DefaultTextModel implements TextModel ,ChangeListener {
private com.taursys.model.ValueHolder valueHolder;
private String propertyName;
private java.text.Format format;
private String formatPattern;
private transient Vector changeListeners;
/**
* Constructs new DefaultTextModel and initializes valueHolder via createDefaultValueHolder
*/
public DefaultTextModel() {
valueHolder = createDefaultValueHolder();
}
/**
* Constructs new DefaultTextModel and sets valueHolder to a VariantValueHolder for given data type.
* @param the data type for the VariantValueHolder (DataType.TYPE_XXXX)
* @throws UnsupportedDataTypeException if invalid javaDataType is given
* @see com.taursys.util.DataTypes
*/
public DefaultTextModel(int javaDataType) throws UnsupportedDataTypeException {
valueHolder = new VariantValueHolder(javaDataType);
}
/**
* Creates default valueHolder to be used by this model.
* Override this method or use the setValueHolder method to change the valueHolder.
* @return a new ValueHolder for this component to use.
*/
protected ValueHolder createDefaultValueHolder() {
return new VariantValueHolder(DataTypes.TYPE_STRING);
}
// ***********************************************************************
// * TEXT PARSE/FORMAT ROUTINES
// ***********************************************************************
/**
* Returns the valueHolder's propertyValue as a String value using Format if defined.
* If the valueHolder's propertyValue is null, it will return an empty
* String ("").
* @return the valueHolder's propertyValue as a formatted String
* @throws ModelException if problem occurs when retrieving value from
* ValueHolder
*/
public String getText()
throws ModelException {
Object value = getValueHolder().getPropertyValue(propertyName);
int javaDataType = getValueHolder().getJavaDataType(propertyName);
if (value == null)
return "";
if (format == null)
return DataTypes.format(javaDataType, value);
else if (format instanceof MessageFormat)
return ((MessageFormat)format).format(new Object[] {value});
else
return format.format(value);
}
/**
* Sets the valueHolder's propertyValue from the given String value to DataType using Format(if defined) to parse.
* If the given String value is null or empty (""), the accessed valueHolder's
* propertyValue is set to null.
* @param the text value used to set the model value
* @throws ModelException if problem parsing or storing value
*/
public void setText(String value) throws ModelException {
int javaDataType = -1;
try {
Object newValue = null;
javaDataType = getValueHolder().getJavaDataType(propertyName);
if (value == null || value.length() == 0) {
newValue = null;
} else if (format == null) {
newValue = DataTypes.parse(javaDataType, value);
} else if (format instanceof MessageFormat) {
Object[] values = ((MessageFormat)format).parse(value);
newValue = DataTypes.convert(javaDataType, values[0]);
} else {
newValue = DataTypes.convert(javaDataType, format.parseObject(value));
}
getValueHolder().setPropertyValue(propertyName, newValue);
} catch (ParseException ex) {
throw new ModelParseException(propertyName, javaDataType, format,
formatPattern, value, ex);
} catch (NumberFormatException ex) {
throw new ModelParseException(propertyName, javaDataType, format,
formatPattern, value, ex);
} catch (UnsupportedConversionException ex) {
throw new ModelException(ModelException.REASON_PARSE_CONVERSION_ERROR,
"Property name: " + propertyName + "\n"
+ "Converting from output of Format type: "
+ format.getClass().getName() + "\n"
+ "to data type of value holder: "
+ DataTypes.getJavaNameForType(javaDataType));
}
}
/**
* Tries to applies the formatPattern to the format. This only occurs if
* the format and formatPattern are not null, and the format is an instance of
* MessageFormat, SimpleDateFormat, ChoiceFormat, or DecimalFormat.
*/
protected void setupFormat() {
// Now apply the format formatPattern if possible
if (format != null && formatPattern != null) {
if (format instanceof MessageFormat)
((MessageFormat)format).applyPattern(formatPattern);
if (format instanceof SimpleDateFormat)
((SimpleDateFormat)format).applyPattern(formatPattern);
if (format instanceof DecimalFormat)
((DecimalFormat)format).applyPattern(formatPattern);
if (format instanceof ChoiceFormat)
((ChoiceFormat)format).applyPattern(formatPattern);
}
}
// ***********************************************************************
// * PROPERTY ACCESSOR METHODS
// ***********************************************************************
/**
* Sets the valueHolder for this model. The valueHolder is the object
* which holds the Object where this model stores the value. The
* default valueHolder is a VariantValueHolder with a javaDataType of String.
* Removes this DefaultTextModel as a change listener from the current
* ValueHolder (if any) and adds this as a change listener to the
* given ValueHolder.
* @param the ValueHolder for this model to use to hold the actual value
*/
public void setValueHolder(com.taursys.model.ValueHolder newValueHolder) {
if (valueHolder != null)
valueHolder.removeChangeListener(this);
valueHolder = newValueHolder;
valueHolder.addChangeListener(this);
}
/**
* Returns the valueHolder for this model. The valueHolder is the object
* which holds the Object where this model stores the value. The
* default valueHolder is a VariantValueHolder with a javaDataType of String.
* @return the ValueHolder used by this model to hold the actual value
*/
public com.taursys.model.ValueHolder getValueHolder() {
return valueHolder;
}
/**
* Sets the propertyName in the valueHolder where this model stores the value.
* This name is ignored if you are using the VariantValueHolder.
* @param the name of the property in the ValueHolder which holds the actual
* value.
*/
public void setPropertyName(String newPropertyName) {
propertyName = newPropertyName;
}
/**
* Returns the propertyName in the valueHolder where this model stores the value.
* This name is ignored if you are using the VariantValueHolder.
* @return the name of the property in the ValueHolder which holds the actual
* value.
*/
public String getPropertyName() {
return propertyName;
}
/**
* Sets the format for this model which is used by set/getText to parse/display values.
* @param the Format object used to format and parse the text value
*/
public void setFormat(java.text.Format newFormat) {
format = newFormat;
setupFormat();
}
/**
* Returns the format for this model which is used by set/getText to parse/display values.
* @return the Format object used to format and parse the text value
*/
public java.text.Format getFormat() {
return format;
}
/**
* Sets the format formatPattern for this model which is used by set/getText to parse/display values.
* @param the pattern to be used by the Format object to format and parse the
* text value.
*/
public void setFormatPattern(String newPattern) {
formatPattern = newPattern;
setupFormat();
}
/**
* Returns the format formatPattern for this model which is used by set/getText to parse/display values.
* @return the pattern to be used by the Format object to format and parse the
* text value.
*/
public String getFormatPattern() {
return formatPattern;
}
// ***********************************************************************
// * CHANGE LISTENER METHODS
// ***********************************************************************
/**
* Invoked when the target ValueHolder of the listener has changed its state.
* This message will simply be propagated to listeners of this component.
*/
public void stateChanged(ChangeEvent e) {
fireStateChanged(e);
}
/**
* Removes the specified change listener so that it no longer receives change events from this model.
* Change events are generated whenever the contents of the value holder change.
*/
public synchronized void removeChangeListener(ChangeListener l) {
if (changeListeners != null && changeListeners.contains(l)) {
Vector v = (Vector) changeListeners.clone();
v.removeElement(l);
changeListeners = v;
}
}
/**
* Adds the specified change listener to receive change events from this model.
* Change events are generated whenever the contents of the value holder change.
*/
public synchronized void addChangeListener(ChangeListener l) {
Vector v = changeListeners == null ? new Vector(2) : (Vector) changeListeners.clone();
if (!v.contains(l)) {
v.addElement(l);
changeListeners = v;
}
}
/**
* Reports a state change to all change listeners.
*/
protected void fireStateChanged(ChangeEvent e) {
if (changeListeners != null) {
Vector listeners = changeListeners;
int count = listeners.size();
for (int i = 0; i < count; i++) {
((ChangeListener) listeners.elementAt(i)).stateChanged(e);
}
}
}
}